import axios from 'axios'
import {
  Modal
} from 'ant-design-vue'
import router from '@/router'
import store from '@/store'
import {
  getStorage,
  setStorage
} from '@/utils/index'
import {message} from 'ant-design-vue'

let isRefreshToken = false // 是否已经发出刷新请求
let timeoutModalTrigger = false // 弹窗的显示开关
let overTimer = 0 // 最多请求5次
const requestList = [] // token过期的api列表
const baseURL = process.env.VUE_APP_BASE_URL
// const baseURL = 'https://sfio.ipsunlight.com/api'

// create an axios instance
const service = axios.create({
  headers: {
    'content-type': 'application/json;charset=UTF-8'
  },
  baseURL, // api的base_url
  timeout: 65 * 1000, // request timeout
  withCredentials: true
})

// 检查接口是否是属于数据中心的token
const checkIsDatabaseApi = function (url) {
  return /^\/ourchem-middle\/data\/search\/query/.test(url)
}

// 已完成token刷新
const refreshFinished = function (url) {
  return (
    url.indexOf('/login') !== -1 ||
    url.indexOf('/ourchem-middle/oauth/refresh') !== -1
  )
}

// 根据api不同设置不同的token
const settingToken = function (config) {
  let token = getStorage('token', 0) ?
    `${getStorage('token', 0)}` :
    `Bearer ${getStorage('visitor', 0)}`
  if (checkIsDatabaseApi(config.url)) {
    // 如果是数据中心的token
    token = getStorage('database_token', 0)
  }
  if (token) {
    config.headers.Authorization = token
  }
}

// 不需要携带token的api
const whiteListNoTokenApi = function (url) {
  const list = ['/captchaImage', '/refresh/token', '/login']
  let need = true
  for (let part of list) {
    if (url == part) {
      need = false
      return need
    }
  }
  return need
}
//重写baseurl, 不需要带/api
const noWithApi = function(config) {
  const reg = /\.json$/
  if (reg.test(config.url)) {
    config.baseURL = config.baseURL.replace('/api', '')
  }
}

// 401 弹窗提示
const tipsAccountTimeout = function () {
  if (timeoutModalTrigger) return
  timeoutModalTrigger = true
  Modal.warning({
    onCancel: function () {
      router.push({
        name: 'Login'
      })
      timeoutModalTrigger = false
    },
    onOk: function () {
      router.push({
        name: 'Login'
      })
      timeoutModalTrigger = false
    },
    footer: null,
    title: '系统提示',
    content: '因长时间未操作，或因其他用户登录此账号而被登出，请重新登录',
    maskClosable: true
  })
}

// request拦截器
service.interceptors.request.use(
  config => {
    settingToken(config) // 给config设置不同api下的不同token
    noWithApi(config)
    if (!whiteListNoTokenApi(config.url)) {
      // 不需要携带token的接口
      delete config.headers.Authorization
    }
    return config
  },
  error => {
    Promise.reject(error)
  }
)
let isRefreshing = false
// 重试队列，每一项将是一个待执行的函数形式
let requests = []
// response 拦截器
// 给实例添加一个setToken方法，用于登录后将最新token动态添加到header，同时将token保存在localStorage中
service.setToken = token => {
  service.defaults.headers.Authorization = token
  setStorage('visitor', token, 0)
}
service.interceptors.response.use(
  response => {
    let role = getStorage('role', 0)
    const {
      code
    } = response.data
    if (code === 401) {
      const {
        config
      } = response
      if (role === 'youke' || role === 'visitor') {
        if (!isRefreshing) {
          isRefreshing = true
          let form = {
            email: 'visitor@qq.com',
            password: '123456'
          }
          store
            .dispatch('user/LoginForm', form)
            .then(res => {
              const {
                token
              } = res
              service.setToken(token)
              config.headers.Authorization = token
              config.baseURL = ''
              // 已经刷新了token，将所有队列中的请求进行重试
              requests.forEach(cb => cb(token))
              requests = []
              return service(config)
            })
            .catch(error => {
              console.error('refreshtoken error =>', error)
              window.location.href = '/'
            })
            .finally(() => {
              isRefreshing = false
            })
        }
        // 正在刷新token，将返回一个未执行resolve的promise
        return new Promise(resolve => {
          // 将resolve放进队列，用一个函数形式来保存，等token刷新后直接执行
          requests.push(token => {
            config.baseURL = ''
            config.headers.Authorization = token
            resolve(service(config))
          })
        })
      } 
      else {
        message.warning('登录失效，请重新登录！')
        setStorage('token', '', 0)
        setTimeout(()=>{
          window.location.replace('/#/login')
        },500)
      }
    } else {
      if (refreshFinished(response.config.url)) {
        // 只要其中一个不是刷新token得请求，得到正常响应，就重置次数限制
        overTimer = 0
      }
      return response.data
    }
  },
  error => {
    if (error.response && error.response.status) {
      const {
        status,
        config
      } = error.response
      if (status === 401 && overTimer < 2) {
        const isRefreshMiddleToken = checkIsDatabaseApi(config.url)
        if (!getStorage('token', 0) || isRefreshMiddleToken) {
          // 没有token 或者是 数据中心的token过期
          return refreshVisiterToken(config, isRefreshMiddleToken)
        }
        if (getStorage('token', 0)) {
          setStorage('token', '', 0)
          tipsAccountTimeout() // 长时间未操作弹窗提示
        }
      }
    }
    return Promise.reject(error)
  }
)

// 无感知刷新游客token
const refreshVisiterToken = async function (config, isRefreshMiddleToken) {
  if (!isRefreshToken) {
    isRefreshToken = true // token已经重新请求了
    if (isRefreshMiddleToken) {
      // 刷新数据中心的token
      // await store.dispatch('user/getDatabaseBinToken')
    } else {
      await store.dispatch('user/getVisiterToken') // 请求和设置结果
    }
    while (requestList.length > 0) {
      requestList.shift()() // 按顺序执行回调
    }
    overTimer++
    isRefreshToken = false
    return service(config)
  } else {
    return new Promise(resolve => {
      requestList.push(() => {
        settingToken(config) // 给config加上token
        resolve(service(config))
      })
    })
  }
}

export default service